#include <rtthread.h>
#include <rtdevice.h>
#include "uc_seg_resend_manager.h"
#include "uc_mask_ope.h"
#include "uc_log.h"
static t_seg_resend_manager *gp_resend_manager = RT_NULL;

void package_clear_resend_flag(char *mask, unsigned short loss_number)
{
    if (loss_number > 0)
    {
        int bit_num = (loss_number - 1);
        CLEAR_BIT(mask[bit_num >> 3], (bit_num % 8));
    }
}

void package_set_resend_flag(char *mask, unsigned short loss_number)
{
    int bit_num = (loss_number - 1);
    SET_BIT(mask[bit_num >> 3], (bit_num % 8));
}

unsigned char package_get_resend_flag(char *mask, unsigned short loss_number)
{
    int bit_num = (loss_number - 1);

    return GET_BIT(mask[bit_num >> 3], (bit_num % 8));
}

#if 0
void packege_reset_timer(void* timer_handle, int timeout)
{
    if (RT_NULL != timer_handle && timeout > 0)
    {
        rt_timer_stop((rt_timer_t)timer_handle);
        rt_timer_control((rt_timer_t)timer_handle, RT_TIMER_CTRL_SET_TIME, (void *)&timeout);
        rt_timer_start((rt_timer_t)timer_handle);
    }
}
#endif

t_seg_resend_manager *packege_init_resend_seg_manager(void (*timer_func)(void *parameter),
                                                      void *parameter,
                                                      int timeout,
                                                      unsigned int dest_addr,
                                                      unsigned char page_num,
                                                      int all_num)
{
    int len = 0;
    t_seg_resend_manager *seg_resend_manage = rt_malloc(sizeof(t_seg_resend_manager));
    if (RT_NULL == seg_resend_manage)
    {
        TRACE_E("seg_resend_manage malloc err");
        return RT_NULL;
    }

    rt_memset(seg_resend_manage, 0, sizeof(t_seg_resend_manager));

    if (RT_NULL == seg_resend_manage->resend_seg_timer)
    {
        // start timer.
        // this timer is used to wait for the retransmission timeout to end.
        // reset this time every time a resend request msg is received.
        seg_resend_manage->resend_seg_timer = (void *)rt_timer_create("resend",
                                                                      timer_func,
                                                                      (void *)seg_resend_manage,
                                                                      timeout, // ms
                                                                      RT_TIMER_FLAG_ONE_SHOT | RT_TIMER_FLAG_SOFT_TIMER);

        // TRACE_I("resend_seg_timer seg_resend_manage 0x%x", seg_resend_manage);

        if (RT_NULL == seg_resend_manage->resend_seg_timer)
        {
            TRACE_E("packege_init_resend_seg_manager create timer err");
            rt_free(seg_resend_manage);
            return RT_NULL;
        }
        seg_resend_manage->parameter = parameter;
        seg_resend_manage->timeout = timeout;
        rt_timer_start((rt_timer_t)seg_resend_manage->resend_seg_timer);
    }

    len = GET_BYTE_NUM(all_num);

    // initialize data management mask base on the number of sent packet
    seg_resend_manage->mask = rt_malloc(len);
    if (RT_NULL == seg_resend_manage->mask)
    {
        TRACE_E("seg_resend_manage->mask  malloc err");
        rt_timer_stop((rt_timer_t)seg_resend_manage->resend_seg_timer);
        rt_timer_delete((rt_timer_t)seg_resend_manage->resend_seg_timer);
        rt_free(seg_resend_manage);
        return RT_NULL;
    }

    rt_memset(seg_resend_manage->mask, BLOCK_UNRESEND_FLAG, len);
    seg_resend_manage->mask_bit_num = (unsigned short)(all_num & 0xFFFF);
    seg_resend_manage->page_num = page_num;
    seg_resend_manage->dest_addr = dest_addr;

    gp_resend_manager = seg_resend_manage;

    return seg_resend_manage;
}

int packege_clear_resend_seg_manager(t_seg_resend_manager *seg_resend_manage)
{
    if (RT_NULL != seg_resend_manage->resend_seg_timer)
    {
        rt_timer_stop((rt_timer_t)seg_resend_manage->resend_seg_timer);
        rt_timer_delete((rt_timer_t)seg_resend_manage->resend_seg_timer);
    }

    if (RT_NULL == seg_resend_manage->mask)
    {
        rt_free(seg_resend_manage->mask);
    }

    // rt_memset(&g_seg_resend_manage, 0, sizeof(struct segment_resend_manage));
    rt_free(seg_resend_manage);

    seg_resend_manage = RT_NULL;

    gp_resend_manager = RT_NULL;

    return 0;
}

t_seg_resend_manager *packege_get_resend_seg_manager(void)
{
    return gp_resend_manager;
}
